package com.autumn.sms.service.services.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.autumn.application.dto.PageQueryResult;
import com.autumn.application.dto.input.DefaultPrimaryKeyInput;
import com.autumn.application.dto.input.QueryCriteriaItemInput;
import com.autumn.mybatis.criterion.Criteria;
import com.autumn.mybatis.criterion.ISpecifyUpdateSection;
import com.autumn.mybatis.criterion.Query;
import com.autumn.sms.service.consts.ServiceConsts;
import com.autumn.sms.service.entities.PlatformInfo;
import com.autumn.sms.service.entities.PlatformTemplate;
import com.autumn.sms.service.entities.PlatformTemplateParameter;
import com.autumn.sms.service.entities.StandardTemplate;
import com.autumn.sms.service.entities.StandardTemplateParameter;
import com.autumn.sms.service.repositories.IPlatformInfoRepository;
import com.autumn.sms.service.repositories.IPlatformTemplateParameterRepository;
import com.autumn.sms.service.repositories.IPlatformTemplateRepository;
import com.autumn.sms.service.repositories.IStandardTemplateParameterRepository;
import com.autumn.sms.service.repositories.IStandardTemplateRepository;
import com.autumn.sms.service.services.ICacheService;
import com.autumn.sms.service.services.IPlatformTemplateService;
import com.autumn.sms.service.services.dto.input.PageQueryByPlatformIdAndTemplateIdInput;
import com.autumn.sms.service.services.dto.input.PageQueryByPlatformIdInput;
import com.autumn.sms.service.services.dto.input.PlatformTemplateInput;
import com.autumn.sms.service.services.dto.input.PlatformTemplateUpdateInput;
import com.autumn.sms.service.services.dto.output.PlatformTemplateOutput;
import com.autumn.sms.service.services.dto.output.PlatformTemplateParameterOutput;
import com.autumn.sms.service.utils.AuditUtils;
import com.autumn.util.AutoMapUtils;
import com.autumn.util.DataRollbackException;
import com.autumn.validation.ValidationException;

/**
 * 平台模板服务
 * 
 * @author JuWa ▪ Zhang
 * @date 2018年1月13日
 * @since jdk 1.8
 */
@Service
public class PlatformTemplateServiceImpl extends AbstractBasicService<IPlatformTemplateRepository, PlatformTemplate>
		implements IPlatformTemplateService {

	@Autowired
	private ICacheService cacheService;

	@Autowired
	private IPlatformInfoRepository platformInfoRepo;
	@Autowired
	private IPlatformTemplateRepository platformTemplateRepo;

	@Autowired
	private IPlatformTemplateParameterRepository platformTemplateParamRepo;

	@Autowired
	private IStandardTemplateRepository standardTemplateRepo;

	@Autowired
	private IStandardTemplateParameterRepository standardTemplateParamRepo;

	@Override
	@Transactional(rollbackFor = DataRollbackException.class)
	public PlatformTemplateOutput add(PlatformTemplateInput input) {
		checkIsExistPlatform(input.getPlatformId());
		checkIsExistStandardTemplate(input.getStandardTemplateId());
		checkIsDuplicatePlatformTemplate(input.getStandardTemplateId(), input.getPlatformId(), input.getSignName());
		checkIsDuplicateSameTemplateId(input.getCode(), input.getPlatformId());
		PlatformTemplate template = AutoMapUtils.mapTo(PlatformTemplate.class, input);
		template.insertAuditingInitialize();
		// 新增平台模板设置为草稿状态
		template.setStatus(ServiceConsts.Status.STATUS_DRAFT);
		platformTemplateRepo.insert(template);
		// 添加该平台模板下的平台模板参数集合
		List<PlatformTemplateParameterOutput> parameterOutputs = batchInsertPlatformTemplateParam(template);
		PlatformTemplateOutput platformTemplateOutput = AutoMapUtils.mapTo(PlatformTemplateOutput.class, template);
		platformTemplateOutput.setParameters(parameterOutputs);
		return platformTemplateOutput;
	}

	/**
	 * 批量插入平台模板参数
	 * 
	 * @return
	 * @param parameters
	 *              平台模板参数输入集合
	 */
	private List<PlatformTemplateParameterOutput> batchInsertPlatformTemplateParam(PlatformTemplate template) {
		List<PlatformTemplateParameter> parameters = template.getParameters();
		List<PlatformTemplateParameterOutput> parameterOutputs = new ArrayList<>();
		if (parameters != null && parameters.size() > 0) {
			Long standardTemplateId = template.getStandardTemplateId();
			for (int i = 0; i < parameters.size(); i++) {
				PlatformTemplateParameter item = parameters.get(i);
				item.setTemplateId(template.getId());
				item.setAutoSortId(i + 1);
				// 根据标准模板ID，标准模板参数名，检测标准模板参数记录是否存在，并获取友好名设置给对应的平台模板参数友好名
				Query query = new Query(StandardTemplateParameter.class);
				String standardParameterName = item.getStandardParameterName();
				query.eq("templateId", standardTemplateId).eq("name", standardParameterName);
				StandardTemplateParameter standardTemplateParameter = standardTemplateParamRepo
						.selectFirst(query.builderSection());
				if (standardTemplateParameter == null) {
					throw new ValidationException(String.format("标准模板ID为[ %s ] ，参数名name为 [%s]  的标准模板参数记录不存在",
							standardTemplateId, standardParameterName));
				}
				item.setFriendlyName(standardTemplateParameter.getFriendlyName());
			}
			platformTemplateParamRepo.batchInsert(parameters);
			parameterOutputs = AutoMapUtils.mapList(parameters, PlatformTemplateParameterOutput.class);
		}
		return parameterOutputs;
	}

	/**
	 * 检测同一平台下同一个平台模板ID的记录是否已存在
	 * 
	 * @param code
	 *              平台模板code
	 * @param platformId
	 *              平台ID
	 */
	private void checkIsDuplicateSameTemplateId(String code, long platformId) {
		Query query = new Query(PlatformTemplate.class);
		// 2.同一平台+同一个平台模板 不能重复
		query.eq("code", code).eq("platformId", platformId).eq("isDelete", false);
		PlatformTemplate template = platformTemplateRepo.selectFirst(query.builderSection());
		if (template != null) {
			throw new ValidationException(
					String.format("主键ID为[ %s ] 的平台下对应平台模板code为 [%s]  的记录已存在", platformId, code));
		}
	}

	/**
	 * 检测标准模板ID是否存在
	 * 
	 * @param standardTemplateId
	 */
	private void checkIsExistStandardTemplate(long standardTemplateId) {
		Query query = new Query(StandardTemplate.class);
		AuditUtils.filterDelete(query);
		query.eq("id", standardTemplateId);
		StandardTemplate template = standardTemplateRepo.selectFirst(query.builderSection());
		if (template == null) {
			throw new ValidationException(String.format("主键ID为 [%s] 标准模板不存在", standardTemplateId));
		}
	}

	/**
	 * 检测平台是否存在
	 * 
	 * @param platformId
	 */
	private void checkIsExistPlatform(long platformId) {
		Query query = new Query(PlatformInfo.class);
		AuditUtils.filterDelete(query);
		query.eq("id", platformId);
		PlatformInfo platform = platformInfoRepo.selectFirst(query.builderSection());
		if (platform == null) {
			throw new ValidationException(String.format("主键ID为 [%s]的平台不存在", platformId));
		}
	}

	/**
	 * 检测同一平台下同一个标准模板ID，同一个签名的记录是否已存在
	 * 
	 * @param standardTemplateId
	 *              标准短信模板ID
	 * @param platformId
	 *              平台ID
	 * @param signName
	 *              平台模板的签名
	 */
	private void checkIsDuplicatePlatformTemplate(long standardTemplateId, long platformId, String signName) {
		Query query = new Query(PlatformTemplate.class);
		AuditUtils.filterDelete(query);
		// 1.同一平台+同一个标准模板 不能重复
		query.eq("standardTemplateId", standardTemplateId).eq("platformId", platformId).eq("signName", signName);
		PlatformTemplate template = platformTemplateRepo.selectFirst(query.builderSection());
		if (template != null) {
			throw new ValidationException(String.format("主键ID为[ %s ] 的平台下对应标准模板ID为 [%s]，签名为[ %s ] 的记录已存在",
					platformId, standardTemplateId, signName));
		}
	}

	@Override
	@Transactional(rollbackFor = DataRollbackException.class)
	public PlatformTemplateOutput modify(PlatformTemplateInput input) {
		PlatformTemplateUpdateInput updateInput = (PlatformTemplateUpdateInput) input;
		PlatformTemplate platformTemplate = checkIsExistEntityByPrimaryId(updateInput.getId());
		if (platformTemplate.getStatus() == ServiceConsts.Status.STATUS_RELEASE) {
			throw new ValidationException("发布状态的平台模板不能修改");
		}
		boolean flag = false;
		if (!updateInput.getStandardTemplateId().equals(platformTemplate.getStandardTemplateId())) {
			checkIsExistStandardTemplate(updateInput.getStandardTemplateId());
			flag = true;
		}
		boolean flag1 = false;
		if (!updateInput.getPlatformId().equals(platformTemplate.getPlatformId())) {
			checkIsExistPlatform(updateInput.getPlatformId());
			flag = true;
			flag1 = true;
		}
		String signName = updateInput.getSignName();
		if (flag || (!platformTemplate.getSignName().equals(signName))) {
			checkIsDuplicatePlatformTemplate(input.getStandardTemplateId(), input.getPlatformId(), signName);
		}
		String code = input.getCode();
		if (flag1 || (!code.equals(platformTemplate.getCode()))) {
			checkIsDuplicateSameTemplateId(code, input.getPlatformId());
		}
		AutoMapUtils.map(updateInput, platformTemplate);
		platformTemplate.updateAuditing();
		// 设置为草稿状态
		platformTemplate.setStatus(ServiceConsts.Status.STATUS_DRAFT);
		platformTemplateRepo.update(platformTemplate);
		// 删除该平台模板下的平台模板参数集合，然后重新添加
		Criteria criteria = new Criteria(PlatformTemplateParameter.class);
		criteria.eq("templateId", updateInput.getId());
		platformTemplateParamRepo.deleteByWhere(criteria.builderSection());
		// 添加该平台模板下的平台模板参数集合
		List<PlatformTemplateParameterOutput> parameterOutputs = batchInsertPlatformTemplateParam(platformTemplate);
		PlatformTemplateOutput platformTemplateOutput = AutoMapUtils.mapTo(PlatformTemplateOutput.class,
				platformTemplate);
		platformTemplateOutput.setParameters(parameterOutputs);
		return platformTemplateOutput;
	}

	@Override
	public void delete(DefaultPrimaryKeyInput input) {
		PlatformTemplate platformTemplate = checkIsExistEntityByPrimaryId(input.getId());
		if (platformTemplate.getStatus() == ServiceConsts.Status.STATUS_RELEASE) {
			throw new ValidationException("发布状态的平台模板不能修改");
		}
		ISpecifyUpdateSection section = AuditUtils.softDeleteById(PlatformTemplate.class, input.getId());
		platformTemplateRepo.updateBySpecify(section);
		// 删除该平台模板下的平台模板参数集合，
		Criteria criteria = new Criteria(PlatformTemplateParameter.class);
		criteria.eq("templateId", input.getId());
		platformTemplateParamRepo.deleteByWhere(criteria.builderSection());
	}

	@Override
	public PlatformTemplateOutput get(DefaultPrimaryKeyInput input) {
		PlatformTemplate platformTemplate = checkIsExistEntityByPrimaryId(input.getId());
		// 获取该平台下的平台模板参数集合
		Query query = new Query(PlatformTemplateParameter.class);
		query.eq("templateId", platformTemplate.getId());
		List<PlatformTemplateParameter> selectList = platformTemplateParamRepo.selectList(query.builderSection());
		List<PlatformTemplateParameterOutput> parameterOutputs = AutoMapUtils.mapList(selectList,
				PlatformTemplateParameterOutput.class);
		PlatformTemplateOutput platformTemplateOutput = AutoMapUtils.mapTo(PlatformTemplateOutput.class,
				platformTemplate);
		platformTemplateOutput.setParameters(parameterOutputs);
		return platformTemplateOutput;
	}

	@Override
	protected IPlatformTemplateRepository getRepository() {
		return platformTemplateRepo;
	}

	@Override
	protected Class<PlatformTemplate> getEntityClass() {
		return PlatformTemplate.class;
	}

	@Override
	public void release(DefaultPrimaryKeyInput input) {
		PlatformTemplate platformTemplate = checkIsExistEntityByPrimaryId(input.getId());
		if (platformTemplate.getStatus() == ServiceConsts.Status.STATUS_RELEASE) {
			throw new ValidationException(String.format("主键ID为 [%s] 的平台模板记录已发布", input.getId()));
		}
		// 检测该平台模板所在平台是否已发布
		Long primaryKey = platformTemplate.getPlatformId();
		Query query = AuditUtils.generateQueryById(PlatformInfo.class, primaryKey);
		AuditUtils.filterDelete(query);
		PlatformInfo platformInfo = platformInfoRepo.selectFirst(query.builderSection());
		if (platformInfo.getStatus() != ServiceConsts.Status.STATUS_RELEASE) {
			throw new ValidationException(String.format("主键ID为 [%s] 的平台记录未发布，不能在此平台发布之前发布该平台下的平台模板", primaryKey));
		}
		// 检测该平台模板对应的标准模板是否发布
		primaryKey = platformTemplate.getStandardTemplateId();
		query = AuditUtils.generateQueryById(StandardTemplate.class, primaryKey);
		AuditUtils.filterDelete(query);
		StandardTemplate standardTemplate = standardTemplateRepo.selectFirst(query.builderSection());
		if (standardTemplate.getStatus() != ServiceConsts.Status.STATUS_RELEASE) {
			throw new ValidationException(String.format("主键ID为 [%s] 的标准模板记录未发布，不能在此标准模板发布之前发布此平台模板", primaryKey));
		}
		platformTemplate.updateAuditing();
		platformTemplate.setStatus(ServiceConsts.Status.STATUS_RELEASE);
		platformTemplateRepo.update(platformTemplate);

		// 刷新redis缓存
		cacheService.removeAllSendTemplate();
	}

	@Override
	public void disable(DefaultPrimaryKeyInput input) {
		PlatformTemplate platformTemplate = checkIsExistEntityByPrimaryId(input.getId());
		if (platformTemplate.getStatus() == ServiceConsts.Status.STATUS_DISABLE) {
			throw new ValidationException(String.format("平台模板表中主键ID为 [%s] 的记录已停用", input.getId()));
		}
		platformTemplate.updateAuditing();
		platformTemplate.setStatus(ServiceConsts.Status.STATUS_DISABLE);
		platformTemplateRepo.update(platformTemplate);

		// 刷新redis缓存
		cacheService.removeAllSendTemplate();
	}

	@Override
	public PageQueryResult<PlatformTemplateOutput> pageQueryByPlatformId(PageQueryByPlatformIdInput input) {
		Query query = new Query(PlatformTemplate.class);
		List<QueryCriteriaItemInput> criterias = input.getCriterias();
		if (criterias != null && criterias.size() > 0) {
			query.criteria(criterias);
		}
		query.eq("isDelete", false).eq("platformId", input.getPlatformId());
		int count = platformTemplateRepo.countByWhere(query.builderSection());
		int maxValue = getPageMaxValue();
		if (input.getPageSize() > maxValue) {
			input.setPageSize(maxValue);
		}
		PageQueryResult<PlatformTemplateOutput> result = new PageQueryResult<>(input.getCurrentPage(),
				input.getPageSize(), count);
		if (count > 0) {
			query.page(result.getCurrentPage(), result.getPageSize());
			List<PlatformTemplate> selectList = platformTemplateRepo.selectList(query.builderSection());
			result.setItems(AutoMapUtils.mapList(selectList, PlatformTemplateOutput.class));
		}
		return result;
	}

	@Override
	public PageQueryResult<PlatformTemplateOutput> pageQueryByPlatformIdAndTemplateId(
			PageQueryByPlatformIdAndTemplateIdInput input) {
		Query query = new Query(PlatformTemplate.class);
		List<QueryCriteriaItemInput> criterias = input.getCriterias();
		if (criterias != null && criterias.size() > 0) {
			query.criteria(criterias);
		}
		query.eq("isDelete", false).eq("platformId", input.getPlatformId()).eq("standardTemplateId", input.getStandardTemplateId());
		int count = platformTemplateRepo.countByWhere(query.builderSection());
		int maxValue = getPageMaxValue();
		if (input.getPageSize() > maxValue) {
			input.setPageSize(maxValue);
		}
		PageQueryResult<PlatformTemplateOutput> result = new PageQueryResult<>(input.getCurrentPage(),
				input.getPageSize(), count);
		if (count > 0) {
			query.page(result.getCurrentPage(), result.getPageSize());
			List<PlatformTemplate> selectList = platformTemplateRepo.selectList(query.builderSection());
			result.setItems(AutoMapUtils.mapList(selectList, PlatformTemplateOutput.class));
		}
		return result;
	}

}
